/**
 * $version:  0.1 
 * $Date: 2011-01-21 
 *
 * Copyright (C) 2010-2011 Jawa Software. All rights reserved.
 *
 */
package org.jawa.learning.webapp.taglib;

import java.awt.Menu;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.TagSupport;

import org.apache.commons.lang.StringUtils;
import org.jawa.core.exception.NotFoundException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 
 * 显示二级子菜单。
 * 
 * @author Y-N
 */
public class DisplaySubMenuTag extends TagSupport {

	private static final long serialVersionUID = -7856656315327706709L;

	private static final Logger Log = LoggerFactory.getLogger(DisplaySubMenuTag.class);

	protected JspWriter out;

	// 菜单组件的 html id
	private String id;

	// 菜单仓库在内存中的名称
	private String repository;

	// 菜单的 target
	private String target;

	// 菜单最外层样式
	private String headerClass;

	// 菜单内层样式
	private String subHeaderClass;

	// 菜单的 css Class
	private String cssClass;

	// 菜单的 css Class
	private String activeClass;

	// 只显示顶级菜单
	private Long parentMenuId;

	// 当前页面菜单编号
	private Long pageID;

	/**
	 * 执行菜单标签
	 */
	public int doStartTag() throws JspException {

		HttpServletRequest request = (HttpServletRequest) pageContext.getRequest();

		MenuRepository repository = null;
		MenuComponent parrentMenu = null;

		pageID = (Long) request.getAttribute("pageID");

		if (pageID == null) {
			pageID = -1L;
		}

		if (repository == null) {
			// 取出菜单仓库
			repository = (MenuRepository) pageContext.findAttribute(this.repository);
		}

		if (repository == null) {
			Log.info("没有找到可显示的菜单");
			return EVAL_PAGE;
		}

		if (parrentMenu == null) {
			// 取出要显示的上级菜单
			parrentMenu = repository.getMenu(parentMenuId);
		}

		if (parrentMenu == null) {
			Log.info("没有找到可显示的上级菜单");
			return EVAL_PAGE;
		}

		out = pageContext.getOut();

		List<MenuComponent> topMenus = parrentMenu.getComponents();

		try {

			out.println("<ul id=\"" + StringUtils.trimToEmpty(id) + "\" class=\""
					+ StringUtils.trimToEmpty(headerClass) + "\">");

			for (Iterator<MenuComponent> iterator = topMenus.iterator(); iterator.hasNext();) {
				MenuComponent topMenu = (MenuComponent) iterator.next();
				displayComponents(topMenu, 0);
			}

			out.println("</ul>");

		} catch (Exception e) {
			Log.error("显示菜单出错!", e);
		}
		return EVAL_PAGE;
	}

	/**
	 * 显示某一个菜单以及下级菜单组件。
	 * 
	 * @param menu
	 *            要显示的菜单组件
	 * @param level
	 *            要显示的菜单组件的级别
	 * @throws JspException
	 * @throws IOException
	 */
	protected void displayComponents(MenuComponent menu, int level) throws JspException, IOException {

		// 如果菜单没有定义URL
		if (null == menu.getMenuUrl() || "".equals(menu.getMenuUrl())) {
			// menu.setMenuUrl("javascript:void(0);");
			menu.setMenuUrl(null);
		}

		// 取出当前菜单组件的下级菜单组件
		MenuComponent[] components = menu.getMenuComponents();

		String css = StringUtils.trimToEmpty(cssClass);

		if (pageID.intValue() == menu.getId().intValue()) {
			css = activeClass;
		}

		// 如果下级中存在可以显示的菜单，即有权限显示
		if (hasViewableChildren(menu)) {

			out.println("<li class=\"" + StringUtils.trimToEmpty(css) + "\">");

			out.print("<a ");

			if (null != menu.getMenuUrl()) {
				out.print(" href=\"" + menu.getMenuUrl() + "\" ");
			}

			if (null != target) {
				out.print(" target=\"" + target + "\" ");
			}
			out.println(" >" + menu.getMenuName() + "</a>");

			out.println("<ul id=\"" + StringUtils.trimToEmpty(id) + ":" + menu.getId() + "\" class=\""
					+ StringUtils.trimToEmpty(subHeaderClass) + "\">");

			for (int i = 0; i < components.length; i++) {
				// 判断当前下级菜单的权限，是否有权限显示
				if (isAllowed(components[i].getId())) {

					// 如果仍然存在下级菜单
					if (hasViewableChildren(components[i])) {
						// 显示当前菜单以及下级菜单
						displayComponents(components[i], level + 1);

					} else {

						css = StringUtils.trimToEmpty(cssClass);

						if (pageID.intValue() == components[i].getId().intValue()) {
							css = activeClass;
						}

						out.println("<li class=\"" + StringUtils.trimToEmpty(css) + "\">");

						out.print("<a  href=\"" + components[i].getMenuUrl() + "\" ");

						if (null != target) {
							out.print(" target=\"" + target + "\" ");
						}
						out.println(" >" + components[i].getMenuName() + "</a>");

						out.println("</li>");
					}
				}
			}

			out.println("</ul>");

			out.println("</li>");
		} else {

			out.println("<li class=\"" + StringUtils.trimToEmpty(css) + "\">");

			out.print("<a  href=\"" + menu.getMenuUrl() + "\" ");

			if (null != target) {
				out.print(" target=\"" + target + "\" ");
			}
			out.println(" >" + menu.getMenuName() + "</a>");

			out.println("</li>");
		}
	}

	/**
	 * 是否允许显示当前菜单,方便以后加入权限控制。
	 * 
	 * @param menuId
	 *            菜单编号
	 * @return
	 */
	public boolean isAllowed(Long menuId) {
		return true;
	}

	/**
	 * 当前菜单的下级菜单中是否有可能显示的。
	 * 
	 * @param menu
	 * @return
	 */
	private boolean hasViewableChildren(MenuComponent menu) {
		for (int i = 0; i < menu.getMenuComponents().length; i++) {
			if (isAllowed(menu.getMenuComponents()[i].getId())) {
				return true;
			}
		}
		return false;
	}

	public void release() {
		this.repository = null;
		this.target = null;
	}

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	public void setRepository(String repository) {
		this.repository = repository;
	}

	public String getRepository() {
		return repository;
	}

	public void setTarget(String target) {
		this.target = target;
	}

	public String getTarget() {
		return target;
	}

	public void setCssClass(String cssClass) {
		this.cssClass = cssClass;
	}

	public String getCssClass() {
		return cssClass;
	}

	public String getHeaderClass() {
		return headerClass;
	}

	public void setHeaderClass(String headerClass) {
		this.headerClass = headerClass;
	}

	public String getActiveClass() {
		return activeClass;
	}

	public void setActiveClass(String activeClass) {
		this.activeClass = activeClass;
	}

	public Long getParentMenuId() {
		return parentMenuId;
	}

	public void setParentMenuId(Long parentMenuId) {
		this.parentMenuId = parentMenuId;
	}

	public String getSubHeaderClass() {
		return subHeaderClass;
	}

	public void setSubHeaderClass(String subHeaderClass) {
		this.subHeaderClass = subHeaderClass;
	}
}
